﻿using System;

namespace suamod.core
{
    using SanlieHash;
    using SanlieHash.Fast;
    using SanlieHash.OtherHash;
    public class SuaPin
    {
        // 摘要计算 2025A  ，可能性0 - 999
        public static string Pin_2025A(string password)
        {
            var timestamp = SuaTime.Now_2025A();
            var radomkey = SuaRadom.MakeNumberAndText(10);
            timestamp = FastGuoMi.EncryptSM4(timestamp, radomkey);
            var zuc = FastGuoMi.GetZUC(timestamp, FastGuoMi.EncryptSM4(timestamp, FastHash.GetSha3_512(timestamp+password)));
            zuc.Jump(314);
            var pin = zuc.NextHex();
            var adler = new ADLER32();
            var pin2 = adler.Make(FastEncode.DecodeHex(FastGuoMi.GetSM3(pin + timestamp)));
            zuc = FastGuoMi.GetZUC(pin2, FastGuoMi.GetSM3(pin));
            zuc.Jump(314);
            return allnum(FastGuoMi.GetSM3(zuc.NextHex()).Substring(0, 3)) +radomkey+ timestamp;
        }
        public static bool Verify_2025A(string _pin, string password)
        {
            var radomkey = _pin.Substring(3, 10);
            var timestamp = FastGuoMi.DecryptSM4(_pin.Substring(13), radomkey);
            if (!SuaTime.Verify_2025A(timestamp)) return false;
            timestamp = FastGuoMi.EncryptSM4(timestamp, radomkey);
            var zuc = FastGuoMi.GetZUC(timestamp, FastGuoMi.EncryptSM4(timestamp, FastHash.GetSha3_512(timestamp + password)));
            zuc.Jump(314);
            var pin = zuc.NextHex();
            var adler = new ADLER32();
            var pin2 = adler.Make(FastEncode.DecodeHex(FastGuoMi.GetSM3(pin+ timestamp)));
            zuc = FastGuoMi.GetZUC(pin2, FastGuoMi.GetSM3(pin));
            zuc.Jump(314);
            return allnum((FastGuoMi.GetSM3(zuc.NextHex()).Substring(0, 3))) + radomkey + timestamp == _pin;
        }
        public static string Pin_2025A_ma(string guid, string password, string pin2025a)
        {
            var timestamp = pin2025a;
            var zuc = FastGuoMi.GetZUC(timestamp, FastGuoMi.EncryptSM4(timestamp, password + guid+ timestamp));
            zuc.Jump(314);
            var pin = zuc.NextHex();
            var adler = new ADLER32();
            var pin2 = adler.Make(FastEncode.DecodeHex(FastGuoMi.GetSM3(pin + timestamp+ guid)));
            zuc = FastGuoMi.GetZUC(pin2, FastGuoMi.GetSM3(pin));
            zuc.Jump(314);
            return allnum(zuc.NextHex().Substring(0, 6));
        }
        public static bool Verify_2025A_ma(string _pin, string guid, string password, string pin2025a)
        {
            var radomkey = pin2025a.Substring(3, 10);
            var timestamp = FastGuoMi.DecryptSM4(pin2025a.Substring(13), radomkey);
            if (!SuaTime.Verify_2025A(timestamp)) return false;
            timestamp = pin2025a;
            var zuc = FastGuoMi.GetZUC(timestamp, FastGuoMi.EncryptSM4(timestamp, password + guid + timestamp));
            zuc.Jump(314);
            var pin = zuc.NextHex();
            var adler = new ADLER32();
            var pin2 = adler.Make(FastEncode.DecodeHex(FastGuoMi.GetSM3(pin + timestamp + guid)));
            zuc = FastGuoMi.GetZUC(pin2, FastGuoMi.GetSM3(pin));
            zuc.Jump(314);
            return allnum(zuc.NextHex().Substring(0, 6)) == _pin;
        }
        internal static string allnum(string hex)
        {
            var rlt = string.Empty;
            foreach (var i in hex.ToUpper())
            {
                if (i >= 'A') rlt += (9 - (i - 'A')).ToString();
                else rlt += i;
            }
            return rlt;
        }
    }
}
